-- require("plugin.cmp")
local status_cmp, cmp = pcall(require, "cmp")
if not status_cmp then
  vim.notify("not found cmp")
  return
end

-- lspkind
local status_lspkind, lspkind = pcall(require, "lspkind")
if not status_lspkind then
  vim.notify("not found lspkind")
  return
end

-- luasnip
local snip_status_ok, luasnip = pcall(require, "luasnip")
if not snip_status_ok then
  vim.notify("not found luasnip")
  return
end

-- autopairs
local status_npairs, npairs = pcall(require, "nvim-autopairs")
if not status_npairs then
  vim.notify("not found nvim-autopairs")
  return
end

npairs.setup({
  check_ts = true,
  ts_config = {
    lua = { "string" }, -- it will not add a pair on that treesitter node
    javascript = { "template_string" },
    java = false, -- don't check treesitter on java
  },
})

local defaults = require("cmp.config.default")()
local cmp_autopairs = require("nvim-autopairs.completion.cmp")

---@diagnostic disable-next-line: missing-fields
cmp.setup({
  preselect = cmp.PreselectMode.None,
  -- completion = {
  -- menu: display options in a menu
  -- menuone: automatically select the first option of the menu
  -- preview: automatically display the completion candiate as you navigate the menu
  -- noselect: prevent neovim from automatically selecting a completion option while navigating the menu
  -- competeopt = "menu,menuone,preview,noselect"
  -- },
  --选择窗口显示边框suggestions
  window = {
    -- completion = cmp.config.window.bordered(),
    documentation = cmp.config.window.bordered(),
  },
  -- Specify the snippet engine
  snippet = {
    expand = function(args)
      -- vim.snippet.expand(args.body)
      luasnip.lsp_expand(args.body) -- For `luasnip` users.
    end,
  },
  experimental = {
    -- 编辑时预显示 代码提示
    ghost_text = true,
    native_menu = false,
  },
  completion = {
    completeopt = "menu,menuone,noinsert",
  },
  -- Completion source
  sources = cmp.config.sources({
    { name = "nvim_lsp" },
    { name = "luasnip" },
    { name = "cmdline" },
    { name = "path" },
    -- { name = "copilot" },
    -- { name = "async_path" },
    -- { name = "lazydev" },
  }, { { name = "buffer" } }),
  confirm_opts = {
    behavior = cmp.ConfirmBehavior.Replace,
    select = false,
  },
  mapping = cmp.mapping.preset.insert({
    -- previous suggestion
    ["<C-p>"] = cmp.mapping.select_prev_item(),
    -- next suggestion
    ["<C-n>"] = cmp.mapping.select_next_item(),
    ["<C-b>"] = cmp.mapping.scroll_docs(-4),
    ["<C-f>"] = cmp.mapping.scroll_docs(4),
    -- show completion suggestions
    ["<C-Space"] = cmp.mapping.complete({}),
    -- close completion window
    ["<C-e>"] = cmp.mapping.abort(),
    -- confirm completion, only when you explicitly selected an option
    ["<CR>"] = cmp.mapping.confirm({
      behavior = cmp.ConfirmBehavior.Replace,
      select = true,
    }),
    ["<Tab>"] = cmp.mapping(function(fallback)
      if cmp.visible() then
        cmp.select_next_item()
      elseif luasnip.expandable() then
        luasnip.expand()
      elseif luasnip.expand_or_jumpable() then
        luasnip.expand_or_jump()
      elseif check_backspace() then
        fallback()
      else
        fallback()
      end
    end, { "i", "s" }),
    ["<S-Tab>"] = cmp.mapping(function(fallback)
      if cmp.visible() then
        cmp.select_prev_item()
      elseif luasnip.jumpable(-1) then
        luasnip.jump(-1)
      else
        fallback()
      end
    end, { "i", "s" }),
  }),

  -- Display type icons with lspkind-nvim
  ---@diagnostic disable-next-line: missing-fields
  formatting = {
    -- 显示的列表列序列
    fields = { "kind", "abbr", "menu" },
    format = lspkind.cmp_format({
      -- options: 'text', 'text_symbol', 'symbol_text', 'symbol'
      -- mode = "symbol_text",
      mode = "symbol", -- show only symbol annotations
      -- default: 'default'
      preset = "codicons",
      -- symbol_map = require("confit.iconskind"),

      maxwidth = 150, -- prevent the popup from showing more than provided characters (e.g 50 will not show more than 50 characters)
      -- The function below will be called before any actual modifications from lspkind
      -- so that you can provide more controls on popup customization. (See [#30](https://github.com/onsails/lspkind-nvim/pull/30))
      before = function(entry, vim_item)
        --- @cast vim_item vim.CompletedItem
        -- Source Displays the source of the hint
        if entry.source.name == "rg" or entry.source.name == "buffer" then
          vim_item.dup = nil
        end
        vim_item.menu = "[" .. string.upper(entry.source.name) .. "]"
        return vim_item
      end,
      -- symbol_map = { Copilot = "" },
      -- 选择列表图标显示
      -- symbol_map = require("config.icons")["kind"],
      symbol_map = require("config.icons").kind,
    }),
  },
  sorting = defaults.sorting,
})

cmp.setup.cmdline(":", {
  mapping = cmp.mapping.preset.cmdline(),
  sources = cmp.config.sources({
    { name = "path" },
  }, {
    {
      name = "cmdline",
      option = {
        ignore_cmds = { "Man", "!" },
      },
    },
  }),
})
-- cmp.setup.cmdline(":", {
--   mapping = cmp.mapping.preset.cmdline(),
--   sources = cmp.config.sources({
--     { name = "async_path" },
--   }, {
--     { name = "cmdline" },
--   }),
-- })

cmp.setup.cmdline({ "/", "?" }, {
  mapping = cmp.mapping.preset.cmdline(),
  sources = cmp.config.sources({
    { name = "nvim_lsp_document_symbol" },
  }, {
    { name = "buffer" },
  }),
})

cmp.event:on("confirm_done", cmp_autopairs.on_confirm_done())
